package com.bbva.itradecomex.controller;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;

import org.apache.log4j.Logger;
import org.primefaces.event.TabChangeEvent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.jsf.FacesContextUtils;

import com.bbva.itradecomex.bo.iface.TableroFiaBO;
import com.bbva.itradecomex.domain.FiaVencido;
import com.bbva.itradecomex.util.Constantes;
import com.bbva.itradecomex.util.ITradexUtil;
import com.bbva.itradecomex.util.MessageProvider;
import com.thoughtworks.xstream.XStream;

@Controller
@RequestScoped
@ManagedBean
public class FiaVencidoController {
	
	private static final Logger log = Logger.getLogger(FiaVencidoController.class);
	
	private static final XStream XSTREAM = new XStream();
	
	@Autowired
	private TableroFiaBO TablerofiaBO;
	
	private TreeNode rootImp;
	private TreeNode rootExp;
	
	private FiaVencido footerImp;
	private FiaVencido footerExp;
	private FiaVencido footerTotalImpExp;

	public void onPageLoad(ComponentSystemEvent event) {
		try {
			if (!FacesContext.getCurrentInstance().isPostback()) {
				cargarArbolData();
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(),e);
		}
	}
	
	public void onTabChange(TabChangeEvent event) {
		if("tba1".equals(event.getTab().getId())){
			cargarArbolData();
		}else if("tba2".equals(event.getTab().getId())){
			FacesContext context = FacesContext.getCurrentInstance();
			FiaProximoVencController fiaProximoVencController = (FiaProximoVencController)FacesContextUtils
										.getWebApplicationContext(context).getBean("fiaProximoVencController");
			fiaProximoVencController.cargarArbolData();
		}
	}

	private void cargarArbolData(){
		try {
			FacesContext context = FacesContext.getCurrentInstance();
			FiaProximoVencController fiaProximoVencController = (FiaProximoVencController)FacesContextUtils
										.getWebApplicationContext(context).getBean("fiaProximoVencController");
			fiaProximoVencController.inicializarValores();
			inicializarValores();
			
			cargarTreeVencidoImp();
			cargarTreeVencidoExp();			
			
			setFooterTotalImpExp();
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(),e);
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
					MessageProvider.getInstance().getValue("MSG_ERROR_TITLE_GENERAL"),
					MessageProvider.getInstance().getValue("MSG_ERROR_DESCRIP_GENERAL")));
		}
	}
	
	private void cargarTreeVencidoImp(){
		try {
			List<FiaVencido> listFiaVencidoImp = TablerofiaBO.getListFiaVencidoImp();	
			rootImp = iniciarCrearTreeNode(listFiaVencidoImp, 0);
			updateTreeNode(rootImp);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(),e);
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
					MessageProvider.getInstance().getValue("MSG_ERROR_TITLE_GENERAL"),
					MessageProvider.getInstance().getValue("MSG_ERROR_DESCRIP_GENERAL")));
		}
	}
	
	private void cargarTreeVencidoExp(){
		try {
			List<FiaVencido> listFiaVencidoExp = TablerofiaBO.getListFiaVencidoExp();
			rootExp = iniciarCrearTreeNode(listFiaVencidoExp, 1);
			updateTreeNode(rootExp);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(),e);
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
					MessageProvider.getInstance().getValue("MSG_ERROR_TITLE_GENERAL"),
					MessageProvider.getInstance().getValue("MSG_ERROR_DESCRIP_GENERAL")));
		}
	}
	
	private TreeNode iniciarCrearTreeNode(List<FiaVencido> listFiaVenc, int tipo) throws Exception{
		TreeNode rootTree = crearTreeNode(listFiaVenc);
		if(rootTree != null && rootTree.getChildCount() > 0){
			ITradexUtil.configInitialTreeNode(rootTree, false);
			switch(tipo){
				case 0: setFooterImpExp(listFiaVenc, footerImp); break;
				case 1: setFooterImpExp(listFiaVenc, footerExp); break;
			}
		}
		return rootTree;
	}
	
	private TreeNode crearTreeNode(List<FiaVencido> list) throws Exception {
		
		TreeNode root = null;
		
		if(list != null){
			root = new DefaultTreeNode(Constantes.TREE_ROOT, null);
			if(list.size() > 0){
				TreeNode treeNode;
		        for (int i = 0; i < list.size(); i++) {
		        	FiaVencido fiaVencido = list.get(i);
		            
		            if (fiaVencido.getCodClasePadre() == null) {
		            	FiaVencido fiaVencidoTree = new FiaVencido();
		            	fiaVencidoTree.setDescClase(fiaVencido.getDescClase());		            	
		            	fiaVencidoTree.setTotOper(fiaVencido.getTotOper());
		            	fiaVencidoTree.setTotMonto(fiaVencido.getTotMonto());
		            	fiaVencidoTree.setRango1Oper(fiaVencido.getRango1Oper());
		            	fiaVencidoTree.setRango1Monto(fiaVencido.getRango1Monto());
		            	fiaVencidoTree.setRango2Oper(fiaVencido.getRango2Oper());
		            	fiaVencidoTree.setRango2Monto(fiaVencido.getRango2Monto());
		            	fiaVencidoTree.setRango3Oper(fiaVencido.getRango3Oper());
		            	fiaVencidoTree.setRango3Monto(fiaVencido.getRango3Monto());
		                
		                treeNode = new DefaultTreeNode(fiaVencidoTree, root);
		                
		                adicionaHijos(fiaVencido, treeNode, list);
		            } else {
		            	break;
		            }
		        }
			}
		}
		
        return root;
    }

    private void adicionaHijos(FiaVencido fiaVencido, TreeNode treeNode, List<FiaVencido> list)
    		 throws Exception {
    	for (int i = 0; i < list.size(); i++) {
    		FiaVencido drFiaVencido = list.get(i);
 
            if (fiaVencido.getCodClase().equals(drFiaVencido.getCodClasePadre())){
            	FiaVencido fiaVencidoTree = new FiaVencido();
            	fiaVencidoTree.setDescClase(drFiaVencido.getDescClase());
            	fiaVencidoTree.setTotOper(drFiaVencido.getTotOper());
            	fiaVencidoTree.setTotMonto(drFiaVencido.getTotMonto());
            	fiaVencidoTree.setRango1Oper(drFiaVencido.getRango1Oper());
            	fiaVencidoTree.setRango1Monto(drFiaVencido.getRango1Monto());
            	fiaVencidoTree.setRango2Oper(drFiaVencido.getRango2Oper());
            	fiaVencidoTree.setRango2Monto(drFiaVencido.getRango2Monto());
            	fiaVencidoTree.setRango3Oper(drFiaVencido.getRango3Oper());
            	fiaVencidoTree.setRango3Monto(drFiaVencido.getRango3Monto());
            	
            	TreeNode drTreeNode = new DefaultTreeNode(fiaVencidoTree, treeNode);
            	
                adicionaHijos(drFiaVencido, drTreeNode, list);
            }
        }
    }
    
	private void updateTreeNode(TreeNode treeNode) {
		if (treeNode != null) {
			List<TreeNode> listTreeNode = treeNode.getChildren();

			for (int i = 0; i < listTreeNode.size(); i++) {
				TreeNode nodeHijo = listTreeNode.get(i);

				if(nodeHijo.getChildren().size() == 0){
					updateNode(nodeHijo);
					break;
				}

				updateTreeNode(nodeHijo);
			}
		}
	}
	
	private void updateNode(TreeNode nodeHijo) {
		if(nodeHijo.getParent() != null && !Constantes.TREE_ROOT.equals(nodeHijo.getParent().getData())){
			TreeNode nodePadre = nodeHijo.getParent();
			List<TreeNode> listTreeNode = nodePadre.getChildren();
			
			BigDecimal totaloOper = new BigDecimal(0);
    		BigDecimal totaloMontoUDS = new BigDecimal(0);
    		BigDecimal totalRango1Oper = new BigDecimal(0);
    		BigDecimal totalRango1MontoUDS = new BigDecimal(0);
    		BigDecimal totalRango2Oper = new BigDecimal(0);
    		BigDecimal totalRango2MontoUDS = new BigDecimal(0);
    		BigDecimal totalRango3Oper = new BigDecimal(0);
    		BigDecimal totalRango3MontoUDS = new BigDecimal(0);
			
			for (int i = 0; i < listTreeNode.size(); i++) {
				TreeNode node = listTreeNode.get(i);
				FiaVencido ob = (FiaVencido)node.getData();
				totaloOper = ITradexUtil.addBigDecimal(totaloOper, ob.getTotOper());
    			totaloMontoUDS = ITradexUtil.addBigDecimal(totaloMontoUDS, ob.getTotMonto());
    			totalRango1Oper = ITradexUtil.addBigDecimal(totalRango1Oper, ob.getRango1Oper());
    			totalRango1MontoUDS = ITradexUtil.addBigDecimal(totalRango1MontoUDS, ob.getRango1Monto());
    			totalRango2Oper = ITradexUtil.addBigDecimal(totalRango2Oper, ob.getRango2Oper());
    			totalRango2MontoUDS = ITradexUtil.addBigDecimal(totalRango2MontoUDS, ob.getRango2Monto());
    			totalRango3Oper = ITradexUtil.addBigDecimal(totalRango3Oper, ob.getRango3Oper());
    			totalRango3MontoUDS = ITradexUtil.addBigDecimal(totalRango3MontoUDS, ob.getRango3Monto());
			}

			((FiaVencido)nodePadre.getData()).setTotOper(totaloOper);
    		((FiaVencido)nodePadre.getData()).setTotMonto(totaloMontoUDS);
    		((FiaVencido)nodePadre.getData()).setRango1Oper(totalRango1Oper);
    		((FiaVencido)nodePadre.getData()).setRango1Monto(totalRango1MontoUDS);
    		((FiaVencido)nodePadre.getData()).setRango2Oper(totalRango2Oper);
    		((FiaVencido)nodePadre.getData()).setRango2Monto(totalRango2MontoUDS);
    		((FiaVencido)nodePadre.getData()).setRango3Oper(totalRango3Oper);
    		((FiaVencido)nodePadre.getData()).setRango3Monto(totalRango3MontoUDS);
			
			updateNode(nodePadre);
		}
	}
    
    private void setFooterImpExp(List<FiaVencido> listFiaVencidoImpExp, FiaVencido footerImpExp){    	
    	if(listFiaVencidoImpExp != null){
    		BigDecimal totaloOper = new BigDecimal(0);
    		BigDecimal totaloMontoUDS = new BigDecimal(0);
    		BigDecimal totalRango1Oper = new BigDecimal(0);
    		BigDecimal totalRango1MontoUDS = new BigDecimal(0);
    		BigDecimal totalRango2Oper = new BigDecimal(0);
    		BigDecimal totalRango2MontoUDS = new BigDecimal(0);
    		BigDecimal totalRango3Oper = new BigDecimal(0);
    		BigDecimal totalRango3MontoUDS = new BigDecimal(0);
    		
    		for(FiaVencido ob : listFiaVencidoImpExp){
    			totaloOper = ITradexUtil.addBigDecimal(totaloOper, ob.getTotOper());
    			totaloMontoUDS = ITradexUtil.addBigDecimal(totaloMontoUDS, ob.getTotMonto());
    			totalRango1Oper = ITradexUtil.addBigDecimal(totalRango1Oper, ob.getRango1Oper());
    			totalRango1MontoUDS = ITradexUtil.addBigDecimal(totalRango1MontoUDS, ob.getRango1Monto());
    			totalRango2Oper = ITradexUtil.addBigDecimal(totalRango2Oper, ob.getRango2Oper());
    			totalRango2MontoUDS = ITradexUtil.addBigDecimal(totalRango2MontoUDS, ob.getRango2Monto());
    			totalRango3Oper = ITradexUtil.addBigDecimal(totalRango3Oper, ob.getRango3Oper());
    			totalRango3MontoUDS = ITradexUtil.addBigDecimal(totalRango3MontoUDS, ob.getRango3Monto());
    		}
    		
    		footerImpExp.setTotOper(totaloOper);
    		footerImpExp.setTotMonto(totaloMontoUDS);
    		footerImpExp.setRango1Oper(totalRango1Oper);
    		footerImpExp.setRango1Monto(totalRango1MontoUDS);
    		footerImpExp.setRango2Oper(totalRango2Oper);
    		footerImpExp.setRango2Monto(totalRango2MontoUDS);
    		footerImpExp.setRango3Oper(totalRango3Oper);
    		footerImpExp.setRango3Monto(totalRango3MontoUDS);
    	}
	}
	
	private void setFooterTotalImpExp(){	
		footerTotalImpExp.setTotOper(ITradexUtil.addBigDecimal(footerImp.getTotOper(), footerExp.getTotOper()));
		footerTotalImpExp.setTotMonto(ITradexUtil.addBigDecimal(footerImp.getTotMonto(), footerExp.getTotMonto()));
		footerTotalImpExp.setRango1Oper(ITradexUtil.addBigDecimal(footerImp.getRango1Oper(), footerExp.getRango1Oper()));
		footerTotalImpExp.setRango1Monto(ITradexUtil.addBigDecimal(footerImp.getRango1Monto(), footerExp.getRango1Monto()));
		footerTotalImpExp.setRango2Oper(ITradexUtil.addBigDecimal(footerImp.getRango2Oper(), footerExp.getRango2Oper()));
		footerTotalImpExp.setRango2Monto(ITradexUtil.addBigDecimal(footerImp.getRango2Monto(), footerExp.getRango2Monto()));
		footerTotalImpExp.setRango3Oper(ITradexUtil.addBigDecimal(footerImp.getRango3Oper(), footerExp.getRango3Oper()));
		footerTotalImpExp.setRango3Monto(ITradexUtil.addBigDecimal(footerImp.getRango3Monto(), footerExp.getRango3Monto()));
	}
	
	public void exportDocument(String tipoDoc){
		if((rootImp != null && rootImp.getChildCount() > 0) ||
				   (rootExp != null && rootExp.getChildCount() > 0)){
			List<FiaVencido> listFiaVencidoImp = new ArrayList<FiaVencido>();
			buildTreeNodeToListReport(rootImp, listFiaVencidoImp, "");
			
			List<FiaVencido> listFiaVencidoExp = new ArrayList<FiaVencido>();
			buildTreeNodeToListReport(rootExp, listFiaVencidoExp, "");
			
			Map<String,Object> parametros = new HashMap<String, Object>();
			parametros.put("listFiaVencidoImp",listFiaVencidoImp);
			parametros.put("listFiaVencidoExp",listFiaVencidoExp);
			parametros.put("obFooterImp",footerImp);
			parametros.put("obFooterExp",footerExp);
			parametros.put("obFooterImpExp",footerTotalImpExp);
			Date mydate = new Date();
			
			String nombreFile = "FIA_VENCIDOS_"+ITradexUtil.convertUtilDateToString(mydate, Constantes.FORMAT_DATE_MM_DD_yyyy);
			
			if(Constantes.ARCHIVO_EXCEL.equals(tipoDoc)){
				ITradexUtil.exportXLSJasperEmptyDS(parametros, "/xmlReport/FiaVencidos/FiaVencido_excel.jasper", nombreFile);
			}else if(Constantes.ARCHIVO_PDF.equals(tipoDoc)){
				ITradexUtil.exportPDFEmptyDS(parametros, "/xmlReport/FiaVencidos/FiaVencido.jasper", nombreFile);
			}
		}
	}
	
	private void buildTreeNodeToListReport(TreeNode node, List<FiaVencido> listFiaVencido, String espacio){
		List<TreeNode> list = node.getChildren();
		boolean continuar = true;
		for(int i=0; i<list.size(); i++){
			TreeNode tnode = list.get(i);
			if(Constantes.TREE_ROOT.equals(node.getData())){
				espacio= "  ";
			}else{
				if(i == 0){
					espacio = espacio + "      ";
				}
			}
			
			if(tnode.getChildren().size() == 0){
				continuar = false;
			}
			
			FiaVencido fiaVencido = (FiaVencido)XSTREAM.fromXML(
					XSTREAM.toXML((FiaVencido)tnode.getData()));
			
			fiaVencido.setDescClase(espacio + fiaVencido.getDescClase());
			listFiaVencido.add(fiaVencido);
			
			if(continuar){
				buildTreeNodeToListReport(tnode, listFiaVencido, espacio);	
			}
		}
	}
	
	public void inicializarValores(){
		initBodyTree();
		initFooter();
	}
	
	private void initBodyTree(){
		rootImp = null;
		rootExp = null;
	}

	private void initFooter(){
		footerImp = new FiaVencido();
		footerExp = new FiaVencido();
		footerTotalImpExp = new FiaVencido();
	}

	public TreeNode getRootImp() {
		return rootImp;
	}

	public void setRootImp(TreeNode rootImp) {
		this.rootImp = rootImp;
	}

	public TreeNode getRootExp() {
		return rootExp;
	}

	public void setRootExp(TreeNode rootExp) {
		this.rootExp = rootExp;
	}

	public FiaVencido getFooterImp() {
		return footerImp;
	}

	public void setFooterImp(FiaVencido footerImp) {
		this.footerImp = footerImp;
	}

	public FiaVencido getFooterExp() {
		return footerExp;
	}

	public void setFooterExp(FiaVencido footerExp) {
		this.footerExp = footerExp;
	}

	public FiaVencido getFooterTotalImpExp() {
		return footerTotalImpExp;
	}

	public void setFooterTotalImpExp(FiaVencido footerTotalImpExp) {
		this.footerTotalImpExp = footerTotalImpExp;
	}
}
